package com.ransj.iphone.view;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Formatter.BigDecimalLayoutForm;

import com.ransj.iphone.IKey;
import com.ransj.iphone.IKeyListener;
import com.ransj.iphone.LockScreenActivity;
import com.ransj.iphone.MainActivity;
import com.ransj.iphone.R;
import com.ransj.iphone.SpKey;
import com.ransj.iphone.R.drawable;
import com.ransj.iphone.R.layout;
import com.ransj.iphone.R.string;
import com.ransj.iphone.utils.ILockScreen;
import com.ransj.iphone.utils.ILog;
import com.ransj.iphone.utils.IScreenShot;
import com.ransj.iphone.utils.ITracker;
import com.ransj.iphone.utils.IUtils;
import com.ransj.iphone.utils.Isp;
import com.ransj.iphone.utils.SuShellExecutor;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.AsyncTask;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

/**
 * view��holder
 * 
 * @author ranshengju
 * 
 */
public class ViewHolder implements IKeyListener {
	public static final String ACTION_CAPTURE = "action_capture_screen";
	private static final String TAG = ViewHolder.class.getSimpleName();
	private static ViewHolder mInstance = new ViewHolder();
	private WindowManager mWMManager;
	private Context mContext;
	private NotificationManager mNoticeManager;
	private AbsView mCurrent, mMain, mNaviPad, mMainPad, mDevicePad, mMinus,
			mShortcuts, mMiniRect, mFunctionsPad;
	private ITracker mTracker;
	private SoundPool mShortSound;
	private int mShotSoundId = -1;
	private boolean mIsFromSc;

	private ViewHolder() {
		SuShellExecutor.getInstance();
	}

	public static ViewHolder getInstance() {
		return mInstance;
	}

	public void init(Context context, WindowManager manager, ITracker tracker) {
		mContext = context;
		mWMManager = manager;
		mTracker = tracker;
		mShortSound = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
		try {
			mShotSoundId = mShortSound.load(context.getAssets().openFd("camera_click.ogg"), 1);
		} catch (IOException e) {
			ILog.getInstance().e(TAG, e);
		}
		createMainView();
	}

	public void createMainView() {
		if (mMain == null) {
			View layout = LayoutInflater.from(mContext).inflate(
					R.layout.iphone_main, null);
			View touch = layout.findViewById(R.id.iphone_main_img);
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.LEFT | Gravity.TOP;
			params.x = Isp.getInstance(mContext).getPrefs()
					.getInt(SpKey.MAIN_X, 0)
					* mWMManager.getDefaultDisplay().getWidth();
			params.y = (int) (Isp.getInstance(mContext).getPrefs()
					.getFloat(SpKey.MAIN_Y, 0) * mWMManager.getDefaultDisplay()
					.getHeight());
			params.width = WindowManager.LayoutParams.WRAP_CONTENT;
			params.height = WindowManager.LayoutParams.WRAP_CONTENT;
			FloatView view = FloatView.createView(layout, touch, params);
			view.setWindowManager(mWMManager);
			view.setMoveable(true);
			view.setCanMinus(true);
			view.setOnKeyEventListener(mInstance, IKey.KEY_MAIN);
			mMain = view;
		} else {
			mMain.setWindowManager(mWMManager);
		}
		mCurrent = mMain;
		mTracker.trackPage("main_view");
	}

	private void createNaviPad() {
		if (mNaviPad == null) {
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.FILL_PARENT;
			params.height = WindowManager.LayoutParams.FILL_PARENT;
			int[] res = {
					R.drawable.selector_bg_device_back,
					R.drawable.selector_bg_key_up,
					R.drawable.selector_bg_key_menu,//
					R.drawable.selector_bg_key_left,
					R.drawable.selector_bg_key_enter,
					R.drawable.selector_bg_key_right,//
					R.drawable.selector_bg_key_home,
					R.drawable.selector_bg_key_down,
					R.drawable.selector_bg_key_back, };//
			int[] keys = {
					IKey.KEY_BACK_MAIN_PAD,
					KeyEvent.KEYCODE_DPAD_UP,
					KeyEvent.KEYCODE_MENU, //
					KeyEvent.KEYCODE_DPAD_LEFT,
					KeyEvent.KEYCODE_DPAD_CENTER,
					KeyEvent.KEYCODE_DPAD_RIGHT,//
					KeyEvent.KEYCODE_HOME, KeyEvent.KEYCODE_DPAD_DOWN,
					KeyEvent.KEYCODE_BACK, };//
			mNaviPad = NinePad.createPad(mContext, res, keys, this, params);
		}
		mNaviPad.setWindowManager(mWMManager);
		mCurrent = mNaviPad;
		mTracker.trackPage("navi_pad");
	}

	private void createMainPad() {
		if (mMainPad == null) {
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.FILL_PARENT;
			params.height = WindowManager.LayoutParams.FILL_PARENT;
			int[] res = { -1, R.drawable.selector_bg_key_power,
					-1,//
					R.drawable.selector_bg_key_star, -1,
					R.drawable.selector_bg_key_device,//
					-1, R.drawable.selector_bg_key_navi, -1, };//
			int[] keys = { -1, KeyEvent.KEYCODE_POWER, -1, IKey.KEY_PAD_STAR,
					-1, IKey.KEY_PAD_DEVICE, -1, KeyEvent.KEYCODE_HOME, -1, };
			mMainPad = NinePad.createPad(mContext, res, keys, this, params);
		}
		mMainPad.setWindowManager(mWMManager);
		mCurrent = mMainPad;
		mTracker.trackPage("main_pad");
	}

	private void createDevicePad() {
		if (mDevicePad == null) {
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.FILL_PARENT;
			params.height = WindowManager.LayoutParams.FILL_PARENT;
			mDevicePad = new DevicePad(mContext, params, this);
		}else{
			((DevicePad) mDevicePad).updateStates();
		}
		mDevicePad.setWindowManager(mWMManager);
		mCurrent = mDevicePad;
		mTracker.trackPage("device_pad");
	}
	
	private void createFunctionsPad() {
		if (mFunctionsPad == null) {
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.FILL_PARENT;
			params.height = WindowManager.LayoutParams.FILL_PARENT;
			mFunctionsPad = new FunctionsPad(mContext, params, this);
		}else{
			((FunctionsPad) mFunctionsPad).updateStates();
		}
		mFunctionsPad.setWindowManager(mWMManager);
		mCurrent = mFunctionsPad;
		mTracker.trackPage("functions_pad");
	}

	private void createMinus() {
		if (mMinus == null) {
			View view = LayoutInflater.from(mContext).inflate(
					R.layout.iphone_minus, null);
			View touch = view.findViewById(R.id.iphone_minus_img);
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.WRAP_CONTENT;
			params.height = WindowManager.LayoutParams.WRAP_CONTENT;
			FloatView floatView = FloatView.createView(view, touch, params);
			floatView.setOnKeyEventListener(this, IKey.KEY_SHORTCUTS);
			floatView.setMoveable(false);
			mMinus = floatView;
		}
		mMinus.setWindowManager(mWMManager);
		mCurrent = mMinus;
		mTracker.trackPage("minus");
	}
	
	private void createMiniRect() {
		if (mMiniRect == null) {
			View view = LayoutInflater.from(mContext).inflate(
					R.layout.iphone_mini_rect, null);
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.WRAP_CONTENT;
			params.height = WindowManager.LayoutParams.WRAP_CONTENT;
			FloatView floatView = FloatView.createView(view, null, params);
			floatView.setOnKeyEventListener(this, IKey.KEY_SHORTCUTS);
			floatView.setMoveable(false);
			mMiniRect = floatView;
		}
		mMiniRect.setWindowManager(mWMManager);
	}
	
	private void createShortCuts() {
		if (mShortcuts == null) {
			LayoutParams params = new LayoutParams();
			params.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
					| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
			params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
			params.format = PixelFormat.RGBA_8888;
			params.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
			params.x = 0;
			params.y = 0;
			params.width = WindowManager.LayoutParams.WRAP_CONTENT;
			params.height = WindowManager.LayoutParams.WRAP_CONTENT;
			ShortCutsList list = null;
			if (SuShellExecutor.getInstance().isRootAllowed()) {
				int[] resId = { R.drawable.selector_bg_key_power_sc,
						R.drawable.selector_bg_key_home_sc,
						R.drawable.selector_bg_key_menu_sc,
						R.drawable.selector_bg_key_back_sc,
						R.drawable.selector_bg_key_star_sc };//
				int[] keyCodes = { IKey.KEY_SC_POWER, IKey.KEY_SC_HOME,
						IKey.KEY_SC_MENU, IKey.KEY_SC_BACK, IKey.KEY_SC_STAR };
				list = ShortCutsList.createList(mContext, params, resId,
						keyCodes);
			} else {
				int[] resId = { R.drawable.selector_bg_key_power_sc,
						R.drawable.selector_bg_key_home_sc,
						R.drawable.selector_bg_key_device_sc,
						R.drawable.selector_bg_key_star_sc };//
				int[] keyCodes = { IKey.KEY_SC_POWER, IKey.KEY_SC_HOME,
						IKey.KEY_SC_DEVICE, IKey.KEY_SC_STAR };
				list = ShortCutsList.createList(mContext, params, resId,
						keyCodes);
			}
			list.setOnKeyEventListener(this);
			mShortcuts = list;
		}
		mShortcuts.setWindowManager(mWMManager);
		mCurrent = mShortcuts;
		mTracker.trackPage("shortcuts");
	}

	public void onKeyEvent(AbsView view, final int keyCode) {
		if (keyCode != -1) {
			switch (keyCode) {
			case IKey.KEY_MAIN:
				trackEvent("key_main");
				view.dispathWindowManager();
				createMainPad();
				break;
			case IKey.KEY_PAD_OUTSIDE:
				trackEvent("key_pad_outside");
				view.dispathWindowManager();
				if(mIsFromSc){
					mIsFromSc = false;
					createShortCuts();
				}else{
					createMainView();
				}
				break;
			case IKey.KEY_PAD_DEVICE:
				trackEvent("key_pad_device");
				view.dispathWindowManager();
				createDevicePad();
				break;
			case IKey.KEY_CAPTURE_SCREEN:
				trackEvent("key_capture_screen");
				view.dispathWindowManager();
				createMainView();
				new ShotTask(this, Bitmap.CompressFormat.PNG, mWMManager).execute();
				break;
			case IKey.KEY_PAD_STAR:
				trackEvent("key_pad_star");
				view.dispathWindowManager();
				createFunctionsPad();
				break;
			case IKey.KEY_PAD_NAVI:
				trackEvent("key_pad_navi");
				view.dispathWindowManager();
				createNaviPad();
				break;
			case IKey.KEY_MAIN_LONG_PRESS:
				trackEvent("key_main_long_press");
				view.dispathWindowManager();
				showNotification();
				break;
			case IKey.KEY_SC_IPHONE:
				view.dispathWindowManager();
				createMainView();
				trackEvent("key_sc_iphone");
				break;
			case IKey.KEY_SC_POWER:
				if(SuShellExecutor.getInstance().isRootAllowed()){
					executeCmd(KeyEvent.KEYCODE_POWER);
				}else{
					startLockActivity();
				}
				trackEvent("key_sc_power");
				break;
			case IKey.KEY_SC_HOME:
				IUtils.back2Home(mContext);
				trackEvent("key_sc_home");
				break;
			case IKey.KEY_SC_MENU:
				executeCmd(KeyEvent.KEYCODE_MENU);
				trackEvent("key_sc_menu");
				break;
			case IKey.KEY_SC_BACK:
				executeCmd(KeyEvent.KEYCODE_BACK);
				trackEvent("key_sc_back");
				break;
			case IKey.KEY_SC_DEVICE:
				view.dispathWindowManager();
				createDevicePad();
				mIsFromSc = true;
				trackEvent("key_sc_device");
				break;
			case IKey.KEY_SC_STAR:
				view.dispathWindowManager();
				createFunctionsPad();
				mIsFromSc = true;
				trackEvent("key_sc_start");
				break;
			case IKey.KEY_SC_MINUS:
				view.dispathWindowManager();
				createMinus();
				trackEvent("key_sc_minus");
				break;
			case IKey.KEY_MAIN_MINUS:
				trackEvent("key_main_minus");
				try {
					view.dispathWindowManager();
					mMiniRect.dispathWindowManager();
				} catch (Exception e) {
					ILog.getInstance().e(TAG, e);
				}
				createMinus();
				break;
			case IKey.KEY_SHORTCUTS:
				trackEvent("key_shortcuts");
				view.dispathWindowManager();
				createShortCuts();
				break;
//				case IKey.KEY_SC_SEARCH:
//				executeCmd(KeyEvent.KEYCODE_SEARCH);
//				trackEvent("key_sc_search");
//				break;
//			case KeyEvent.KEYCODE_DPAD_UP:
//				trackEvent("key_dpad_up");
//				executeCmd(keyCode);
//				break;
//			case KeyEvent.KEYCODE_DPAD_DOWN:
//				trackEvent("key_dpad_down");
//				executeCmd(keyCode);
//				break;
//			case KeyEvent.KEYCODE_DPAD_LEFT:
//				trackEvent("key_dpad_left");
//				executeCmd(keyCode);
//				break;
//			case KeyEvent.KEYCODE_DPAD_RIGHT:
//				trackEvent("key_dpad_right");
//				executeCmd(keyCode);
//				break;
//			case KeyEvent.KEYCODE_DPAD_CENTER:
//				trackEvent("key_dpad_center");
//				executeCmd(keyCode);
//				break;
//			case KeyEvent.KEYCODE_SEARCH:
//				view.dispathWindowManager();
//				createMainView();
//				trackEvent("key_search");
//				executeCmd(keyCode);
//				break;
			case KeyEvent.KEYCODE_POWER:
				view.dispathWindowManager();
				createMainView();
				trackEvent("key_power");
				if(SuShellExecutor.getInstance().isRootAllowed()){
					executeCmd(keyCode);
				}else{
					startLockActivity();
				}
				break;
			case KeyEvent.KEYCODE_HOME:
				view.dispathWindowManager();
				createMainView();
				trackEvent("key_home");
				IUtils.back2Home(mContext);
				break;
			case KeyEvent.KEYCODE_BACK:
				view.dispathWindowManager();
				createMainView();
				trackEvent("key_back");
				executeCmd(keyCode);
				break;
			case KeyEvent.KEYCODE_MENU:
				view.dispathWindowManager();
				createMainView();
				trackEvent("key_menu");
				executeCmd(keyCode);
				break;
			case IKey.KEY_BACK_MAIN_PAD:
				view.dispathWindowManager();
				if(mIsFromSc){
					mIsFromSc = false;
					createShortCuts();
				}else{
					createMainPad();
				}
				trackEvent("key_device_back");
				break;
			case IKey.KEY_MINI_ENTER:
				if(mCurrent == mMain){
					createMiniRect();
				}
				break;
			case IKey.KEY_MINI_EXIT:
				try {
					mMiniRect.dispathWindowManager();
				} catch (Exception e) {
					ILog.getInstance().e(TAG, e);
				}
				break;
			case KeyEvent.KEYCODE_UNKNOWN:
				trackEvent("key_unknown");
				executeCmd(keyCode);
				break;
			}
		}
	}

	private void executeCmd(int keyCode) {
		String command = "sh "
				+ mContext.getFileStreamPath(MainActivity.COMMAND_FILE)
						.getAbsolutePath() + " keyevent " + keyCode;
		SuShellExecutor.getInstance().executeCmd(command);
	}

	private void trackEvent(String label) {
		mTracker.trackEvent(ITracker.CATEGORY_BUTTON, ITracker.ACTION_CLICK,
				label);
	}

	private void showNotification() {
		Notification notice = new Notification();
		Intent broadcast = new Intent("notification.broadcast.action");
		PendingIntent pIntent = PendingIntent.getBroadcast(mContext, 0,
				broadcast, PendingIntent.FLAG_UPDATE_CURRENT);
		notice.when = System.currentTimeMillis();
		notice.icon = R.drawable.ic_iphone;
		notice.tickerText = mContext.getString(R.string.notifycation_tick_text);
		notice.flags |= Notification.FLAG_AUTO_CANCEL;
		notice.flags |= Notification.FLAG_NO_CLEAR;
		notice.setLatestEventInfo(mContext,
				mContext.getString(R.string.notifycation_tick_text),
				mContext.getString(R.string.notifycation_tick_tip), pIntent);
		if (mNoticeManager == null) {
			mNoticeManager = (NotificationManager) mContext
					.getSystemService(Activity.NOTIFICATION_SERVICE);
		}
		mNoticeManager.notify(0, notice);
	}
	
	public void onConfigurationChanged(Configuration newConfig) {
		ILog.getInstance().w(TAG, "onConfigurationChanged ORIENTATION_LANDSCAPE : "+(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE));
		ILog.getInstance().w(TAG, "onConfigurationChanged ORIENTATION_PORTRAIT : "+(newConfig.orientation == Configuration.ORIENTATION_PORTRAIT));
		if (mCurrent.equals(mMain) || mCurrent.equals(mMinus)
				|| mCurrent.equals(mShortcuts)) {
			int x = 0, y = 0;
			int width = mWMManager.getDefaultDisplay().getWidth();
			int height = mWMManager.getDefaultDisplay().getHeight();
			if ((width > height && newConfig.orientation == Configuration.ORIENTATION_PORTRAIT)
					|| (height > width && newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE)) {
				int temp = height;
				height = width;
				width = temp;
			}
			if (mCurrent.equals(mMain)) {
				x = Isp.getInstance(mContext).getPrefs()
						.getInt(SpKey.MAIN_X, 0)* width;
				y = (int) (Isp.getInstance(mContext).getPrefs()
						.getFloat(SpKey.MAIN_Y, 0)* height);
			}else if(mCurrent.equals(mMinus)
					|| mCurrent.equals(mShortcuts)){
				x = 0;
				y = 0;
			}
			mCurrent.updatePosition(x, y);
		}
	}
	
	/**
	 * 
	 */
	public void onDestory() {

	}
	
	public void playShotSound(){
		if(mShotSoundId != -1){
			mShortSound.play(mShotSoundId, 1, 1, 5, 0, 1);
		}
	}
	
	public void startLockActivity(){
		Intent lock = new Intent(mContext, LockScreenActivity.class);
		lock.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
		mContext.startActivity(lock);
	}

	private static String getUniqueShotName() {
		return "/sdcard/screenshot/Ishot_"
				+ new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss")
						.format(new Date()) + ".png";
	}

	public static class ShotTask extends AsyncTask<Void, Void, Boolean> {
		private Bitmap.CompressFormat mFormat;
		private WindowManager mWM;
		private ViewHolder mHolder;
		private String mPath;

		public ShotTask(ViewHolder holder, Bitmap.CompressFormat format,
				WindowManager wm) {
			mHolder = holder;
			mFormat = format;
			mWM = wm;
		}

		@Override
		protected Boolean doInBackground(Void... params) {
			mHolder.playShotSound();
			long time = System.currentTimeMillis();
			for (; System.currentTimeMillis() - time < 1000;) {
				Thread.yield();
			}
			mPath = getUniqueShotName();
			return IScreenShot.screenShot(mPath, mFormat, mWM);
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			String tip = null;
			if (result) {
				if (mPath != null) {
					mHolder.mContext.sendBroadcast(new Intent(
							Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri
									.parse("file://" + mPath)));

					ILog.getInstance().d(TAG, "CaptureScreen as file: " + mPath);
				}
				tip = mHolder.mContext.getString(
						R.string.notifycation_screenshot_success, mPath);
			} else {
				tip = mHolder.mContext.getString(
						R.string.notifycation_screenshot_failed);
			}
			Toast.makeText(mHolder.mContext, tip, Toast.LENGTH_SHORT).show();
		}
	}
}
